package com.algrithom.traceback;

import java.util.Arrays;

/**
 * 回溯算法 n皇后问题
 *
 * @author think
 * @version 1.0.0
 * @since 2020/1/14
 */
public class Nquene {
    
    public static void main(String[] args){
        Nquene nquene = new Nquene();
        nquene.nQueensProblem(8);
    }
    
    private void nQueensProblem(int n){
        char[][] board = new char[n][n];
        backtrack(board,0);
    }
    
    void backtrack(char[][] board,int row){
        // 触发结束条件
        if (row == board.length) {
            for (char[] curBoard : board) {
                System.out.println(Arrays.toString(curBoard));
            }
            System.out.println("***********************************************");
            return;
        }
        
        int n = board[row].length;
        for (int col = 0; col < n; col++) {
            // 排除不合法选择
            if (!isValid(board,row,col)) {
                continue;
            }
            // 做选择
            board[row][col] = 'Q';
            // 进入下一行决策
            backtrack(board,row + 1);
            // 撤销选择
            board[row][col] = '.';
        }
    }
    
    boolean isValid(char[][] board,int row,int col){
        int n = board.length;
        // 检查列是否有皇后互相冲突
        for (char[] curBoard : board) {
            if (curBoard[col] == 'Q') {
                return false;
            }
        }
        // 检查右上方是否有皇后互相冲突
        for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        // 检查左上方是否有皇后互相冲突
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }
}
